/*
Auhtor       : Pratibh Prakash
Company      : Fujitsu America
Created Date : 21 Sep-2009
Description  : Trigger populates the Territory Names on Account based on the Billing Postal Code present in Account.

Modified     : Andrey Volosevich
Modified Date: 11 Dec-2009
Description	 : Updated the trigger matching logic to work off of a different field in the PostalCode object. Now runs off of Index1 field. 
			   The index field is a composite (concatened) value of PostalCode (Name) and Country. 
			   This update was made to match new version of Sundog TLR 3.0
*/


trigger updateTerritoryNameField on Account (before insert, after insert, before update) {
        
        Set<String> uniqueZipCountryIndex = new Set<String>();//Set for storing unique potsal codes retrieved from Account reocrds
        List<Account> accountsForProcess = new List<Account>();
        Set<String> accountIdsforWarnings = new Set<String>();
        if(Trigger.isBefore && Trigger.IsInsert){
                for(Integer i=0; i<Trigger.new.size(); i++){
                        uniqueZipCountryIndex.add(Trigger.new[i].BillingPostalCode + '|' + Trigger.new[i].BillingCountry);
                }
                accountsForProcess.addAll(Trigger.new);
        }
        else if(Trigger.isBefore && Trigger.IsUpdate){
                Map<Id, Account> oldAccounts = new Map<Id, Account>();
                for(Integer i=0; i<Trigger.new.size(); i++){
                        //Filtering Account records if value of BillingPostalCode is changed
                        if(Trigger.oldMap.get(Trigger.new[i].Id).BillingPostalCode !=  Trigger.new[i].BillingPostalCode 
							|| Trigger.oldMap.get(Trigger.new[i].Id).BillingCountry !=  Trigger.new[i].BillingCountry
				 			|| Trigger.new[i].IM_Force_Sundog_Terr_Assignment_Update__c == true
			   			  )
			   				{
                                uniqueZipCountryIndex.add(Trigger.new[i].BillingPostalCode + '|' + Trigger.new[i].BillingCountry);
                                accountsForProcess.add(Trigger.new[i]);
                                Trigger.new[i].IM_Force_Sundog_Terr_Assignment_Update__c = false;
                        	}
                }
        }
        if(accountsForProcess.size()>0){
                /*Set for storing value of postal codes for which warning mail has to be sent.
                Set is only used in After insert for getting Ids of Account record for which warning mail has to be sent
                as Id of Account records are generated in before insert event*/
                Set<String> postalCodesForWarning = new Set<String>();
                
                Map<String, Set<String>> zipCountry_TerritoryMap = new Map<String, Set<String>>();//Map for storing Postal Code and corresponing Territory Names
                //Generating map of Postal Code and corresponing Territory Names
                for(sundog_deprm2__Postal_Code__c postalcode: [Select Id, Name, Index_1_PostalCode_Country__c, sundog_deprm2__Partner_Territory__c, 
                														sundog_deprm2__Partner_Territory__r.Name
                                                                from sundog_deprm2__Postal_Code__c
                                                                where Index_1_PostalCode_Country__c IN :uniqueZipCountryIndex]){
                        if(zipCountry_TerritoryMap.containsKey(postalcode.Index_1_PostalCode_Country__c)){
                                if(postalcode.sundog_deprm2__Partner_Territory__c != null){
                                        zipCountry_TerritoryMap.get(postalcode.Index_1_PostalCode_Country__c).add(postalcode.sundog_deprm2__Partner_Territory__r.Name);
                                }
                        }
                        else{
                                if(postalcode.sundog_deprm2__Partner_Territory__c != null){
                                        zipCountry_TerritoryMap.put(postalcode.Index_1_PostalCode_Country__c , new Set<String>());
                                        zipCountry_TerritoryMap.get(postalcode.Index_1_PostalCode_Country__c).add(postalcode.sundog_deprm2__Partner_Territory__r.Name);
                                }
                        }
                }
                
                Set<String> territoryNames;     
                String tempTerritoryNames='';
                
                for(Integer j=0; j<accountsForProcess.size(); j++){
                        //Populating Territory value in Account by matching BillingPostalCode in SunDog PostalCode records.  
                        territoryNames = zipCountry_TerritoryMap.get(accountsForProcess[j].BillingPostalCode + '|' + accountsForProcess[j].BillingCountry);
                        if(territoryNames != null){
                                for(String terrritories: territoryNames){
                                        if((tempTerritoryNames.length()+terrritories.length())<=255){
                                                tempTerritoryNames += '<'+terrritories+'>\n';
                                        }
                                        else{
                                                accountIdsforWarnings.add(accountsForProcess[j].Id);
                                                postalCodesForWarning.add(accountsForProcess[j].BillingPostalCode + '|' + accountsForProcess[j].BillingCountry);
                                                break;
                                        }
                                }
                                accountsForProcess[j].IM_Territories__c = tempTerritoryNames;
                                tempTerritoryNames='';
                                
                        }
                        else{
                                accountsForProcess[j].IM_Territories__c ='';
                        }
                }
                TerritoryWarningEmail.preparepostalCodesForWarning(postalCodesForWarning);
        }
        
        if(Trigger.IsAfter && Trigger.IsInsert){//Filtering out account records for which warning mail has to be sent.
                if(TerritoryWarningEmail.getpostalCodesForWarning().size()>0){
                        for(Integer i=0; i<Trigger.new.size(); i++){
                                if(TerritoryWarningEmail.getpostalCodesForWarning().contains(accountsForProcess[i].BillingPostalCode + '|' + accountsForProcess[i].BillingCountry)){
                                        accountIdsforWarnings.add(Trigger.new[i].Id);
                                }
                        }
                }
        }
        
        if((Trigger.IsAfter && Trigger.IsInsert) || (Trigger.IsBefore && Trigger.IsUpdate)){
                if(accountIdsforWarnings.size()>0){
                        System.debug('***********Going to Send Waring Email*****');
                        TerritoryWarningEmail.sendWarningEmail(accountIdsforWarnings);
                }
        }
}